package org.ia2;

import jade.core.AID;
import jade.core.Agent;
import jade.core.AgentContainer;
import jade.core.behaviours.*;
import jade.domain.DFService;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.UnreadableException;
import jade.wrapper.AgentController;
import jade.wrapper.StaleProxyException;

import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Objects;

public class HostAgent extends Agent {
    private String IPAddr = "0.0.0.0";

    protected void setup (){

        try {
            DFAgentDescription dfd = new DFAgentDescription();
            dfd.setName(getAID());
            DFService.register(this, dfd);
        }catch (Exception e) {
            System.out.println( "Erro teste yellow pages: " + e );
            e.printStackTrace();
        }

        ACLMessage msg = new ACLMessage(ACLMessage.REQUEST);
        msg.setSender(getAID());
        msg.addReceiver(new AID("RoteadorAgent", AID.ISLOCALNAME));
        msg.setOntology("DHCP_REQUEST");
        msg.setContent("Me dê um endereço de IP.");
        send(msg);

        // DHCP client and network input behaviour (recebimento de pacotes)
        addBehaviour (new CyclicBehaviour(this){
            public void action ( ){
                ACLMessage msg = myAgent.receive();
                if (msg != null) {
                    String content = msg.getOntology();
                    if (content.equalsIgnoreCase( "DHCP_RESPONSE")) {
                        System.out.println(this.myAgent.getLocalName() + ": Concessão DHCP por " + msg.getSender().getLocalName() + " = " + msg.getContent() + "\n");
                        setIPAddr(msg.getContent());
                    }else if (content.contains( "NET_PACKET_")){
                        try {
                            Pacote pkt = (Pacote) msg.getContentObject();
                            System.out.println(this.myAgent.getLocalName() + ": Recebido pacote "+ content +" de " + pkt.getSrcIPAddress() + " via " +msg.getSender().getLocalName() + " contém " + pkt.getCorpo());

                            if (!content.equals("NET_PACKET_RES")) {
                                // Monta resposta da requisição.
                                final ACLMessage msg2 = new ACLMessage(ACLMessage.INFORM);
                                msg2.setSender(getAID());
                                msg2.addReceiver(new AID("RoteadorAgent", AID.ISLOCALNAME));
                                msg2.setOntology("NET_PACKET_RES");
                                try {
                                    msg2.setContentObject(new Pacote(
                                            getIPAddr(),
                                            pkt.getSrcIPAddress(),
                                            pkt.getCorpo()
                                    ));
                                } catch (IOException e) {
                                    throw new RuntimeException(e);
                                }
                                System.out.println(this.myAgent.getLocalName() + ": Enviando resposta ao roteador");
                                this.myAgent.send(msg2);
                            }

                        }
                        catch(UnreadableException e){
                            throw new RuntimeException(e);
                        }
                    }else{
                        block();
                    }

                }
            }
        });

        // Network output behaviour (envia requisições)
        addBehaviour (new WakerBehaviour(this, 3000){
            public void handleElapsedTimeout ( ) {
                if (Objects.equals(getLocalName(), "HostAgent")) {
                    System.out.println("\nPreparando novo pacote em " + getLocalName() + "...");
                    ACLMessage msg = new ACLMessage(ACLMessage.REQUEST);
                    msg.setSender(getAID());
                    msg.addReceiver(new AID("RoteadorAgent", AID.ISLOCALNAME));
                    msg.setOntology("NET_PACKET_REQ");
                    try {
                        msg.setContentObject(new Pacote(
                                getIPAddr(),
                                (getIPAddr().equals("192.168.1.2")) ? "192.168.1.3" : "192.168.1.2",
                                "ICMP ECHO (ping)"
                        ));
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                    System.out.println(this.myAgent.getLocalName() + ": Enviando pacote ao roteador");
                    send(msg);
                }
            }

        });
    }

    public void setIPAddr(String IPAddr){
        this.IPAddr = IPAddr;
    }

    public String getIPAddr() {
        return IPAddr;
    }
}
